﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Corina.Controls.Silverlight
{
    public class SmartListBox : ListBox
    {
        #region Properties

        public static readonly DependencyProperty SmartSelectedItemsProperty =
          DependencyProperty.Register("SmartSelectedItems", typeof(INotifyCollectionChanged), typeof(SmartListBox), new PropertyMetadata(OnSmartSelectedItemsPropertyChanged));

        public INotifyCollectionChanged SmartSelectedItems
        {
            get { return (INotifyCollectionChanged)GetValue(SmartSelectedItemsProperty); }
            set { SetValue(SmartSelectedItemsProperty, value); }
        }

        #endregion

        public SmartListBox()
        {
            SelectionChanged += new SelectionChangedEventHandler(BaseListBoxSelectionChanged);
        }

        private static void OnSmartSelectedItemsPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
        {
            var collection = args.NewValue as INotifyCollectionChanged;
            if (collection != null)
            {
                // unsubscribe, before subscribe to make sure not to have multiple subscription
                collection.CollectionChanged -= ((SmartListBox)target).SmartSelectedItemsCollectionChanged;
                collection.CollectionChanged += ((SmartListBox)target).SmartSelectedItemsCollectionChanged;
            }
        }

        void SmartSelectedItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            //Need to unsubscribe from the events so we don't override the transfer
            UnsubscribeFromEvents();

            //Move items from the selected items list to the list box selection
            Transfer(SmartSelectedItems as IList, base.SelectedItems);

            //subscribe to the events again so we know when changes are made
            SubscribeToEvents();
        }

        void BaseListBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            //Need to unsubscribe from the events so we don't override the transfer
            UnsubscribeFromEvents();

            //Move items from the selected items list to the list box selection
            Transfer(base.SelectedItems, SmartSelectedItems as IList);

            //subscribe to the events again so we know when changes are made
            SubscribeToEvents();
        }

        private void SubscribeToEvents()
        {
            SelectionChanged += BaseListBoxSelectionChanged;

            if (SmartSelectedItems != null)
            {
                SmartSelectedItems.CollectionChanged += SmartSelectedItemsCollectionChanged;
            }
        }

        private void Transfer(System.Collections.IList source, IList target)
        {
            if (source == null || target == null)
            {
                return;
            }

            target.Clear();

            foreach (var o in source)
            {
                target.Add(o);
            }
        }

        private void UnsubscribeFromEvents()
        {
            SelectionChanged -= BaseListBoxSelectionChanged;

            if (SmartSelectedItems != null)
            {
                SmartSelectedItems.CollectionChanged -= SmartSelectedItemsCollectionChanged;
            }
        }
    }
}
